/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.admin.client.components;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.elf.gwt.admin.client.AdminComponentController;
import com.elf.gwt.common.client.access.RequestParameter;
import com.elf.gwt.common.client.model.AbbreviatedProductModel;
import com.elf.gwt.common.client.model.AttributeModel;
import com.elf.gwt.common.client.model.AttributeValueModel;
import com.elf.gwt.common.client.model.CurrencyModel;
import com.elf.gwt.common.client.model.DetailedProductModel;
import com.elf.gwt.common.client.model.DiscountCategoryModel;
import com.elf.gwt.common.client.model.EditProductMetaModel;
import com.elf.gwt.common.client.model.ManufacturerModel;
import com.elf.gwt.common.client.model.PriceBreakModel;
import com.elf.gwt.common.client.model.TaxClassModel;
import com.elf.gwt.common.client.utils.CommonUtils;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.DateBox;

/**
 *
 */
public class EditProductComponent extends JSONServerComponent
{	
	protected static final String Insert = "InsertProduct";
	protected static final String Update = "UpdateProduct";
	protected static final String CopyAttributes = "CopyAttributes";

	protected static TaxClassesComponent taxClassesComponent = null;
	protected static DiscountCategoriesComponent discountCategoriesComponent = null;
	protected static ProductOptionsToValuesComponent productOptionsToValuesComponent = null;

	EditProductMetaModel productMetaModel;
	DetailedProductModel productModel;

	protected int selectedGroupId = 0;
	protected int selectedCategoryId = 0;
	protected int selectedProductId = 0;
	protected int selectedCopyProductId = 0;

	protected String action = null;

	protected HashMap<String, Widget> elements = null;
	protected Grid grid;
	protected Grid attributesGrid;
	protected int numberOfPriceBreaksMax;
	protected List<AttributeModel> optionModels;

	/**
	 * Constructor
	 */
	public EditProductComponent(AdminComponentController controller, String stylePrefix)
	{
		super(controller, stylePrefix);
		setupTimer();
		elements = new HashMap<String, Widget>();
		if (taxClassesComponent == null) taxClassesComponent = (TaxClassesComponent)controller.getComponent("TaxClassesComponent");
		if (discountCategoriesComponent == null) discountCategoriesComponent = (DiscountCategoriesComponent)controller.getComponent("DiscountCategoriesComponent");
		if (productOptionsToValuesComponent == null) productOptionsToValuesComponent = (ProductOptionsToValuesComponent)controller.getComponent("ProductOptionsToValuesComponent");
	}

	public void additionalRequestParameters()
	{
		addRequestParameter(new RequestParameter ("productId", selectedProductId));
		addRequestParameter(new RequestParameter ("categoryId", selectedCategoryId));
		addRequestParameter(new RequestParameter("action", action));

		if (action != null && (action.equals(Insert) || action.equals(Update)))
		{
			Iterator<String> iterElements = elements.keySet().iterator();
			while (iterElements.hasNext())
			{
				String key = iterElements.next();
				Widget widget = elements.get(key);
				String value = CommonUtils.getValue(widget);
				addRequestParameter(new RequestParameter(key, value));
			} 
		}
		else if (action != null && action.equals(CopyAttributes))
		{
			addRequestParameter(new RequestParameter ("copyProductId", selectedCopyProductId));
		}
		action = "";
	}

	protected void buildMetaModel(JSONObject jsonObject) throws Exception
	{
		productMetaModel = new EditProductMetaModel(jsonObject);
	}

	protected void buildModel(JSONObject jsonObject) throws Exception
	{
		productModel = new DetailedProductModel(jsonObject, productMetaModel.getImageWidthMax(), productMetaModel.getImageHeightMax(), true);
	}

	public void buildFromModel() throws Exception
	{
		clear();

		//Buttons
		HorizontalPanel buttonPanel = new HorizontalPanel();
		buttonPanel.setStyleName("ZButtons");

		Button backButton = new Button("back", 
				new ClickHandler() {
					public void onClick(ClickEvent event) {
						String history = "CategoriesProductsComponent" + "--" + selectedGroupId + "--" + selectedCategoryId + "--" + 0 + "--" + productModel.getId();
						onSelection(history);
					}}
		);
		backButton.addStyleName("ComponentLink");
		buttonPanel.add(backButton);
		buttonPanel.add(new InlineHTML("&nbsp;&nbsp;"));

		if (productModel.getId() > 0) {
			Button saveButton = new Button("save",
					new ClickHandler() {
						public void onClick(ClickEvent event) {
							submit(Update);
						}}
			);
			saveButton.addStyleName("ComponentLink");
			buttonPanel.add(saveButton);
			buttonPanel.add(new InlineHTML("&nbsp;&nbsp;"));
		}

		else {
			Button saveAsNewButton = new Button("save as new",
					new ClickHandler() {
						public void onClick(ClickEvent event) {
							submit(Insert);
						}}
			);
			saveAsNewButton.addStyleName("ComponentLink");
			buttonPanel.add(saveAsNewButton);
		}

		add(buttonPanel);
		add(new InlineHTML("<br/><br/><br/>"));

		CurrencyModel currencyModel = AdminComponentController.currenciesAdministrationComponent.getCurrencyModel();
		numberOfPriceBreaksMax = productMetaModel.getNumberOfPriceBreaksMax();

		optionModels = productOptionsToValuesComponent.getOptionModels();

		grid = new Grid(33+numberOfPriceBreaksMax, 2);
		add(grid);
		grid.setText(0, 0, "Status:");
		grid.setText(1, 0, "Date Available:");
		grid.setText(2, 0, "Virtual:");
		grid.setText(3, 0, "Manufacturer:");
		grid.setText(4, 0, "Name:");
		grid.setText(5, 0, "Tax Class:");
		grid.setText(6, 0, "Price(" + currencyModel.getCode() + "):");
		grid.setText(7, 0, "Description:");
		grid.setText(8, 0, "Inventory Quantity:");
		grid.setText(9, 0, "Model:");
		grid.setText(10, 0, "Weight:");
		grid.setText(11, 0, "URL:");
		grid.setText(12, 0, "Image:");
		grid.setText(14, 0, "Image:");
		grid.setText(16, 0, "Image:");
		grid.setText(18, 0, "Image:");
		grid.setText(20, 0, "Image:");
		grid.setText(22, 0, "Image:");
		grid.setText(24, 0, "Image:");
		grid.setText(26, 0, "Max Image Width (optional):");
		grid.setText(27, 0, "Max Image Height(optional):");
		grid.setText(28, 0, "Quantity Blocks:");
		grid.setText(29, 0, "Discount Categories:");
		//Price Breaks
		for (int j = 0; j < numberOfPriceBreaksMax; j++)
		{
			int row = 32 + j;
			grid.setText(row, 0, "Price Level " + (j + 1) + ":");
		}

		elements.clear();

		ListBox statusListBox = new ListBox();
		statusListBox.addItem("Published", "1");
		statusListBox.addItem("Unpublished", "0");
		statusListBox.setItemSelected(0, productModel.isStatus());
		statusListBox.setItemSelected(1, !productModel.isStatus());
		elements.put("status", statusListBox);
		grid.setWidget(0, 1, statusListBox);

		DateBox availableDateBox = new DateBox();
		availableDateBox.setFormat(new DateBox.DefaultFormat( CommonUtils.dateFormat));
		availableDateBox.setValue(productModel.getDateAvailable());
		elements.put("availableDate", availableDateBox);
		grid.setWidget(1, 1, availableDateBox);

		ListBox virtualListBox = new ListBox();
		virtualListBox.addItem("No", "0");
		virtualListBox.addItem("Yes", "1");
		virtualListBox.setItemSelected(0, !productModel.isVirtual());
		virtualListBox.setItemSelected(1, productModel.isVirtual());
		elements.put("virtual", virtualListBox);
		grid.setWidget(2, 1, virtualListBox);


		List<ManufacturerModel> manufacturerModels = AdminComponentController.manufacturersAdministrativeComponent.getManufacturerModels();
		ListBox manufacturerListBox = new ListBox();

		Iterator<ManufacturerModel> iter = manufacturerModels.iterator();

		manufacturerListBox.addItem("None", "0");
		if (0 == productModel.getManufacturerId())
		{
			manufacturerListBox.setSelectedIndex(0);
		}

		int i = 1;
		while(iter.hasNext())
		{
			ManufacturerModel model = iter.next();
			String name = model.getName();
			if (model.getId() == 0) continue;
			manufacturerListBox.addItem(name, String.valueOf(model.getId()));
			if (model.getId() == productModel.getManufacturerId())
			{
				manufacturerListBox.setSelectedIndex(i);
			}
			i++;
		}
		elements.put("manufacturerId", manufacturerListBox);
		grid.setWidget(3, 1, manufacturerListBox);

		TextBox nameTextBox = new TextBox();
		nameTextBox.setWidth("300px");
		nameTextBox.setText(productModel.getName());
		elements.put("productName", nameTextBox);
		grid.setWidget(4, 1, nameTextBox);


		i = 0;
		List<TaxClassModel> taxClassModels = taxClassesComponent.getTaxClassModels();
		ListBox taxClassListBox = new ListBox();
		taxClassListBox.addItem("None", "0");
		if (0 == productModel.getTaxClassId())
		{
			taxClassListBox.setSelectedIndex(i);
		}
		i++;
		Iterator<TaxClassModel> iter1 = taxClassModels.iterator();
		while(iter1.hasNext())
		{
			TaxClassModel model = iter1.next();
			taxClassListBox.addItem(model.getTitle() + ": " + model.getDescription(), String.valueOf(model.getId()));
			if (model.getId() == productModel.getTaxClassId())
			{
				taxClassListBox.setSelectedIndex(i);
			}
			i++;
		}
		elements.put("taxClassId", taxClassListBox);
		grid.setWidget(5, 1, taxClassListBox);

		TextBox priceTextBox = new TextBox();
		priceTextBox.setWidth("100px");
		priceTextBox.setText(String.valueOf(productModel.getPrice()));
		elements.put("productPrice", priceTextBox);
		grid.setWidget(6, 1, priceTextBox);

		TextArea descriptionTextArea = new TextArea();
		descriptionTextArea.setWidth("100%");
		descriptionTextArea.setCharacterWidth(100);
		descriptionTextArea.setVisibleLines(20);
		descriptionTextArea.setText(productModel.getDescription());
		elements.put("description", descriptionTextArea);
		grid.setWidget(7, 1, descriptionTextArea);

		TextBox quantityTextBox = new TextBox();
		quantityTextBox.setWidth("100px");
		quantityTextBox.setText(String.valueOf(productModel.getInventoryQuantity()));
		elements.put("inventory", quantityTextBox);
		grid.setWidget(8, 1, quantityTextBox);

		TextBox modelTextBox = new TextBox();
		modelTextBox.setWidth("300px");
		modelTextBox.setText(productModel.getModel());
		elements.put("productModel", modelTextBox);
		grid.setWidget(9, 1, modelTextBox);

		TextBox weightTextBox = new TextBox();
		weightTextBox.setWidth("100px");
		weightTextBox.setText(String.valueOf(productModel.getWeight()));
		elements.put("weight", weightTextBox);
		grid.setWidget(10, 1, weightTextBox);

		TextBox urlTextBox = new TextBox();
		urlTextBox.setWidth("500px");
		urlTextBox.setText(String.valueOf(productModel.getUrl()));
		elements.put("url", urlTextBox);
		grid.setWidget(11, 1, urlTextBox);

		Date now = new Date();
		long intNow = now.getTime();
		FileUpload upload0 = new FileUpload();
		upload0.setName("image-0-" + intNow);
		grid.setWidget(12, 1, upload0);
		String image0 = productModel.getImage();
		if (image0 == null) image0 = "";
		elements.put("image-0", upload0);
		grid.setText(13, 1, image0);

		FileUpload upload1 = new FileUpload();
		upload1.setName("image-1-" + intNow);
		grid.setWidget(14, 1, upload1);
		String image1 = productModel.getImage1();
		if (image1 == null) image1 = "";
		elements.put("image-1", upload1);
		grid.setText(15, 1, image1);

		FileUpload upload2 = new FileUpload();
		upload2.setName("image-2-" + intNow);
		grid.setWidget(16, 1, upload2);
		String image2 = productModel.getImage2();
		if (image2 == null) image2 = "";
		elements.put("image-2", upload2);
		grid.setText(17, 1, image2);

		FileUpload upload3 = new FileUpload();
		upload3.setName("image-3-"+ intNow);
		grid.setWidget(18, 1, upload3);
		String image3 = productModel.getImage3();
		if (image3 == null) image3 = "";
		elements.put("image-3", upload3);
		grid.setText(19, 1, image3);

		FileUpload upload4 = new FileUpload();
		upload4.setName("image-4-" + intNow);
		grid.setWidget(20, 1, upload4);
		String image4 = productModel.getImage4();
		if (image4 == null) image4 = "";
		elements.put("image-4", upload4);
		grid.setText(21, 1, image4);

		FileUpload upload5 = new FileUpload();
		upload5.setName("image-5-" + intNow);
		grid.setWidget(22, 1, upload5);
		String image5 = productModel.getImage5();
		if (image5 == null) image5 = "";
		elements.put("image-5", upload5);
		grid.setText(23, 1, image5);

		FileUpload upload6 = new FileUpload();
		upload6.setName("image-6-" + intNow);
		grid.setWidget(24, 1, upload6);
		String image6 = productModel.getImage6();
		if (image6 == null) image6 = "";
		elements.put("image-6", upload6);
		grid.setText(25, 1, image6);

		TextBox ImageWidthMaxTextBox = new TextBox();
		ImageWidthMaxTextBox.setWidth("100px");
		ImageWidthMaxTextBox.setText(String.valueOf(productModel.getProductImageWidthMax()));
		elements.put("imageWidthMax", ImageWidthMaxTextBox);
		grid.setWidget(26, 1, ImageWidthMaxTextBox);

		TextBox ImageHeightMaxTextBox = new TextBox();
		ImageHeightMaxTextBox.setWidth("100px");
		ImageHeightMaxTextBox.setText(String.valueOf(productModel.getProductImageHeightMax()));
		elements.put("ImageHeightMax", ImageHeightMaxTextBox);
		grid.setWidget(27, 1, ImageHeightMaxTextBox);

		TextBox quantityBlocksTextBox = new TextBox();
		quantityBlocksTextBox.setWidth("100px");
		quantityBlocksTextBox.setText(String.valueOf(productModel.getQuantityBlocks()));
		elements.put("quantityBlocks", quantityBlocksTextBox);
		grid.setWidget(28, 1, quantityBlocksTextBox);

		i = 0;
		List<DiscountCategoryModel> discountCategoryModels = discountCategoriesComponent.getDiscountCategoryModels();
		ListBox discountCategoryListBox = new ListBox();
		discountCategoryListBox.addItem("None", "0");
		if (0 == productModel.getDiscountCategory())
		{
			discountCategoryListBox.setSelectedIndex(i);
		}
		i++;
		Iterator<DiscountCategoryModel> iter2 = discountCategoryModels.iterator();
		while(iter2.hasNext())
		{
			DiscountCategoryModel model = iter2.next();
			discountCategoryListBox.addItem(model.getName(), String.valueOf(model.getId()));
			if (model.getId() == productModel.getDiscountCategory())
			{
				discountCategoryListBox.setSelectedIndex(i);
			}
			i++;
		}
		elements.put("discountCategoryId", discountCategoryListBox);
		grid.setWidget(29, 1, discountCategoryListBox);

		//Price Breaks
		HorizontalPanel hpanel = new HorizontalPanel();
		HTML priceHTML = new HTML("Price");
		priceHTML.setWidth("100px");
		hpanel.add(priceHTML);
		hpanel.add(new InlineHTML("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;From&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity"));
		grid.setWidget(31, 1, hpanel);
		setupPriceBreaks();

		ListBox productsListBox = new ListBox();
		productsListBox.addItem("Select ...", "0");
		productsListBox.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				ListBox productsListBox = (ListBox)event.getSource();
				int selectedIndex = productsListBox.getSelectedIndex();
				String selectedValue = productsListBox.getValue(selectedIndex);
				selectedCopyProductId = Integer.parseInt(selectedValue);
				action = CopyAttributes;
				build(true);
			}
		});
		Iterator<AbbreviatedProductModel> iterProducts = productMetaModel.getProducts().iterator();
		while(iterProducts.hasNext())
		{
			AbbreviatedProductModel model = iterProducts.next();
			productsListBox.addItem(model.getName(), String.valueOf(model.getId()));
		}

		add(productsListBox);
		add(new InlineHTML(" a product to copy attributes from, OR type in attribute information in table below:"));


		add(new InlineHTML("<br/>"));

		//Attributes
		attributesGrid = new Grid(0,0);
		add(attributesGrid);
		setupAttributes();

		add(new InlineHTML("<br/>"));

		onBuilt();
	}

	public boolean updateFromHistoryParameters(String[] params)
	{
		selectedProductId = 0;
		try {
			selectedGroupId = Integer.parseInt(params[1]);
			CatalogGroupComponent catalogGroupComponent = (CatalogGroupComponent) controller.getComponent("CatalogGroupComponent");
			catalogGroupComponent.setSelectedGroupModel(selectedGroupId);	
			catalogGroupComponent.setSelectedInGUI();
			adminController.getNavigationStackPanel().showStack(catalogGroupComponent.getIndex());	

			selectedCategoryId = Integer.parseInt(params[2]);

			selectedProductId = Integer.parseInt(params[3]);
		}
		catch (Exception e) {}

		return super.updateFromHistoryParameters(params);
	}


	protected void setupPriceBreaks()
	{
		List<PriceBreakModel> priceBreakModels = productModel.getPriceBreaks();
		int numberOfPriceBreaks = priceBreakModels.size();
		HorizontalPanel hpanel = new HorizontalPanel();
		HTML priceHTML = new HTML("Price");
		priceHTML.setWidth("100px");
		hpanel.add(priceHTML);
		hpanel.add(new InlineHTML("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;From&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity"));
		grid.setWidget(31, 1, hpanel);
		for (int j = 0; j< numberOfPriceBreaksMax; j++)
		{
			hpanel = new HorizontalPanel();
			TextBox priceBreakQuantityTextBox = new TextBox();
			elements.put("priceBreakQuantity-" + j, priceBreakQuantityTextBox);
			priceBreakQuantityTextBox.setWidth("100px");
			TextBox priceBreakPriceTextBox = new TextBox();
			elements.put("priceBreakPrice-" + j, priceBreakPriceTextBox);
			priceBreakPriceTextBox.setWidth("100px");
			hpanel.add(priceBreakPriceTextBox);
			hpanel.add(new InlineHTML("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;From&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"));
			hpanel.add(priceBreakQuantityTextBox);
			if (j < numberOfPriceBreaks)
			{
				PriceBreakModel priceBreakModel = priceBreakModels.get(j);
				priceBreakQuantityTextBox.setText(String.valueOf(priceBreakModel.getQuantity()));
				priceBreakPriceTextBox.setText(String.valueOf(priceBreakModel.getPrice()));
				CheckBox priceBreakDelete = new CheckBox();
				priceBreakDelete.addStyleName("index:"+j);
				priceBreakDelete.addClickHandler(pbDeleteClickHandler);
				hpanel.add(new InlineHTML("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"));
				hpanel.add(priceBreakDelete);	
				hpanel.add(new InlineHTML("&nbsp;Delete"));			
			}
			grid.setWidget(32+j, 1, hpanel);
		}
	}

	protected ClickHandler pbDeleteClickHandler = new ClickHandler() {
		public void onClick(ClickEvent event) {
			Widget source = (Widget)event.getSource();
			String stylenames = source.getStyleName();
			int loc = stylenames.indexOf("index:");
			stylenames = stylenames.substring(loc+6);
			loc = stylenames.indexOf(" ");
			if (loc > -1) stylenames = stylenames.substring(0, loc);
			int rowIndex = Integer.parseInt(stylenames);
			productModel.getPriceBreaks().remove(rowIndex);
			setupPriceBreaks();

		}
	};

	protected void setupAttributes()
	{
		List<AttributeModel> attributeModels = productModel.getAttributes();

		Iterator<AttributeModel> iterAttributes = attributeModels.iterator();
		int rows = 1;
		while (iterAttributes.hasNext())
		{
			AttributeModel attributeModel = iterAttributes.next();
			List<AttributeValueModel> attributeValueModels = attributeModel.getValues();
			int attributeValueSize = attributeValueModels.size();
			rows = rows + attributeValueSize;
		}

		//int szChildren = this.getWidgetCount();
		attributesGrid = new Grid(rows+10, 9);
		add(attributesGrid);

		attributesGrid.setText(0, 0, "Option Name");
		attributesGrid.setText(0, 1, "Option Value");
		attributesGrid.setText(0, 2, "Sort Order");
		attributesGrid.setText(0, 3, "Prefix");
		attributesGrid.setText(0, 4, "Value Price");
		attributesGrid.setText(0, 5, "Delete");
		if (productMetaModel.getDownloadEnabled())
		{
			attributesGrid.setText(0, 6, "Filename");
			attributesGrid.setText(0, 7, "Expiry Days");
			attributesGrid.setText(0, 8, "Max. Download Count");
		}

		iterAttributes = attributeModels.iterator();
		int rowCnt = 0;
		while (iterAttributes.hasNext())
		{
			AttributeModel attributeModel = iterAttributes.next();
			List<AttributeValueModel> attributeValueModels = attributeModel.getValues();
			int attributeValueSize = attributeValueModels.size();
			for (int j = 0; j < attributeValueSize; j++)
			{
				attributesRow(rowCnt, 
						j,
						attributeValueModels, 
						false);
				rowCnt++;
			}
		}
		for (int j = 0; j < 10; j++)
		{
			attributesRow(rowCnt, 
					j,
					null, 
					true);
			rowCnt++;
		}
	}

	public void attributesRow(int rowCnt, 
			int j,
			List<AttributeValueModel> attributeValueModels, 
			boolean boolLast)
	{
		AttributeValueModel attributeValueModel = null;
		if (!boolLast) attributeValueModel = attributeValueModels.get(j);

		Hidden rowIdHidden = new Hidden();
		rowIdHidden.setName("paId-" + rowCnt);
		if (!boolLast) rowIdHidden.setValue(String.valueOf(attributeValueModel.getRowId()));
		elements.put("paId-" + rowCnt, rowIdHidden);

		ListBox optionNameListBox = new ListBox();
		if (boolLast) optionNameListBox.addItem("N/A", "-1");
		optionNameListBox.setWidth("100px");
		optionNameListBox.addStyleName("index:"+rowCnt);
		optionNameListBox.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				ListBox optionNameListBox = (ListBox)event.getSource();
				int selectedIndex = optionNameListBox.getSelectedIndex();
				String selectedValue = optionNameListBox.getValue(selectedIndex);
				int intValue = Integer.parseInt(selectedValue);
				String stylenames = optionNameListBox.getStyleName();
				int loc = stylenames.indexOf("index:");
				stylenames = stylenames.substring(loc+6);
				loc = stylenames.indexOf(" ");
				if (loc > -1) stylenames = stylenames.substring(0, loc);
				int rowCnt = Integer.parseInt(stylenames);
				ListBox optionValueListBox = (ListBox)attributesGrid.getWidget(rowCnt+1, 1);
				optionValueListBox.clear();
				Iterator<AttributeModel> iterOptions = optionModels.iterator();
				while(iterOptions.hasNext())
				{
					AttributeModel oModel = iterOptions.next();
					if (oModel.getId() == intValue) {
						setOptionValues(optionValueListBox, 0, oModel);
					}
				}					
			}
		});
		elements.put("optionNameId-" + rowCnt, optionNameListBox);
		attributesGrid.setWidget(rowCnt+1, 0, optionNameListBox);

		ListBox optionValueListBox = new ListBox();
		optionValueListBox.setWidth("100px");
		elements.put("optionValueId-" + rowCnt, optionValueListBox);
		attributesGrid.setWidget(rowCnt+1, 1, optionValueListBox);

		Iterator<AttributeModel> iterOptions = optionModels.iterator();
		int io = 0;
		while(iterOptions.hasNext())
		{
			int attributeId = 0;
			int valueId = 0;
			if (!boolLast) {
				attributeId = attributeValueModel.getAttributeId();
				valueId = attributeValueModel.getId();
			}

			AttributeModel oModel = iterOptions.next();
			optionNameListBox.addItem(oModel.getName(), String.valueOf(oModel.getId()));
			if (oModel.getId() == attributeId)
			{
				optionNameListBox.setSelectedIndex(io);
				setOptionValues(optionValueListBox, valueId, oModel);
			}
			io++;
		}

		TextBox sortOrderTextBox = new TextBox();
		sortOrderTextBox.setWidth("100px");
		if (!boolLast) sortOrderTextBox.setText(String.valueOf(j+1));
		elements.put("sortOrder-" + rowCnt, sortOrderTextBox);
		attributesGrid.setWidget(rowCnt+1, 2, sortOrderTextBox);

		ListBox prefixListBox = new ListBox();
		prefixListBox.setWidth("50px");
		prefixListBox.addItem("+");
		prefixListBox.addItem("-");
		if(!boolLast && attributeValueModel.getPrefix().equals("-")) {
			prefixListBox.setSelectedIndex(1);
		}
		else {
			prefixListBox.setSelectedIndex(0);
		}
		elements.put("prefix-" + rowCnt, prefixListBox);
		attributesGrid.setWidget(rowCnt+1, 3, prefixListBox);

		TextBox optionPriceTextBox = new TextBox();
		optionPriceTextBox.setWidth("100px");
		if (!boolLast) optionPriceTextBox.setText(String.valueOf(attributeValueModel.getPrice()));
		elements.put("optionPrice-" + rowCnt, optionPriceTextBox);
		attributesGrid.setWidget(rowCnt+1, 4, optionPriceTextBox);

		if (!boolLast) {
			CheckBox optionDelete = new CheckBox();
			optionDelete.addStyleName("index:"+attributeValueModel.getRowId());
			optionDelete.addClickHandler(attDeleteClickHandler);
			attributesGrid.setWidget(rowCnt+1, 5, optionDelete);
		}

		if (productMetaModel.getDownloadEnabled())
		{
			TextBox filenameTextBox = new TextBox();
			filenameTextBox.setWidth("100px");
			if (!boolLast) filenameTextBox.setText(attributeValueModel.getFilename());
			elements.put("filename-" + rowCnt, filenameTextBox);
			attributesGrid.setWidget(rowCnt+1, 6, filenameTextBox);

			TextBox maxdaysTextBox = new TextBox();
			maxdaysTextBox.setWidth("100px");
			if (!boolLast) maxdaysTextBox.setText(String.valueOf(attributeValueModel.getMaxDays()));
			else maxdaysTextBox.setText(String.valueOf(productMetaModel.getDownloadMaxDays()));
			elements.put("maxdays-" + rowCnt, maxdaysTextBox);
			attributesGrid.setWidget(rowCnt+1, 7, maxdaysTextBox);

			TextBox maxcountTextBox = new TextBox();
			maxcountTextBox.setWidth("100px");
			if (!boolLast) maxcountTextBox.setText(String.valueOf(attributeValueModel.getMaxCount()));
			else maxcountTextBox.setText(String.valueOf(productMetaModel.getDownloadMaxCount()));
			elements.put("maxcount-" + rowCnt, maxcountTextBox);
			attributesGrid.setWidget(rowCnt+1, 8, maxcountTextBox);
		}
	}

	protected void setOptionValues(ListBox optionValueListBox, int valueId, AttributeModel oModel) {
		Iterator<AttributeValueModel> iterValues = oModel.getValues().iterator();
		int i = 0;
		while(iterValues.hasNext())
		{
			AttributeValueModel avModel = iterValues.next();
			optionValueListBox.addItem(avModel.getName(), String.valueOf(avModel.getId()));
			if (avModel.getId() == valueId)
			{
				optionValueListBox.setSelectedIndex(i);
			}
			i++;
		}
	}

	protected ClickHandler attDeleteClickHandler = new ClickHandler() {
		public void onClick(ClickEvent event) {
			Widget source = (Widget)event.getSource();
			String stylenames = source.getStyleName();
			int loc = stylenames.indexOf("index:");
			stylenames = stylenames.substring(loc+6);
			loc = stylenames.indexOf(" ");
			if (loc > -1) stylenames = stylenames.substring(0, loc);
			int rowIndex = Integer.parseInt(stylenames);
			List<AttributeModel> attributeModels = productModel.getAttributes();

			Iterator<AttributeModel> iterAttributes = attributeModels.iterator();
			boolean match = false;
			while (iterAttributes.hasNext())
			{
				AttributeModel attributeModel = iterAttributes.next();
				Iterator<AttributeValueModel> iterValueModels = attributeModel.getValues().iterator();
				while (iterValueModels.hasNext())
				{
					AttributeValueModel attributeValueModel = iterValueModels.next();
					if (attributeValueModel.getRowId() == rowIndex) {
						attributeModel.getValues().remove(attributeValueModel);
						match = true;
						break;
					}
				}
				if (match) break;
			}
			setupAttributes();

		}
	};

	protected void submit(String action)
	{
		if (action.equals(Insert) && productModel.getId() > 0) {
			TextBox nameTextBox = (TextBox) elements.get("productName");
			String name = nameTextBox.getText();
			if (!name.startsWith("Copy of")) {
				name = "Copy of " + name;
				nameTextBox.setText(name);
			}
			elements.put("productName", nameTextBox);
		}
		this.action = action;
		Window.scrollTo(0, 0);
		build(true);
	}
}
